package org.opens.javaskill.design;

import org.junit.Test;

import java.util.Hashtable;
import java.util.Map;

/**
 * 说明:
 *      1. 原型模式的demo.
 */
public class PrototypePattern {

    @Test
    public void testPrototypePattern() throws CloneNotSupportedException {
        ShapeCache.loadCache();
        Shape shapeCache1 = ShapeCache.getShape(1);
        Shape shapeCache2 = ShapeCache.getShape(2);
        Shape shapeCache3 = ShapeCache.getShape(3);

        shapeCache1.draw();
        shapeCache2.draw();
        shapeCache3.draw();
    }

}

abstract class Shape implements Cloneable {

    private Integer id;

    protected String type;

    abstract void draw();

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object clone = null;
        try {
            clone = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
    }

}

class Rectangle extends Shape {

    public Rectangle() {
        this.type = "rectangle";
    }

    @Override
    void draw() {
        System.out.println("Inside Rectangle::draw() method.");
    }

}

class Square extends Shape {

    public Square() {
        this.type = "square";
    }

    @Override
    void draw() {
        System.out.println("Inside Square::draw() method.");
    }

}

class Circle extends Shape {

    public Circle(){
        type = "circle";
    }

    @Override
    public void draw() {
        System.out.println("Inside Circle::draw() method.");
    }

}

/**
 * 说明:
 *      1. 将创建一个抽象类 Shape 和扩展了 Shape 类的实体类。下一步是定义类 ShapeCache，该类把 shape 对象存储在一个 Hashtable 中，
 *      并在请求的时候返回它们的克隆。
 *      2. 当直接创建对象的代价比较大时，则采用这种模式进行缓存对象, 然后在需要的时候返回这个对象的克隆对象.
 */
class ShapeCache {

    private static Map<Integer, Shape> shapeMap = new Hashtable<>();

    public static Shape getShape(Integer id) throws CloneNotSupportedException {
        Shape shape = shapeMap.get(id);
        return (Shape) shape.clone();
    }

    public static void loadCache() {
        Circle circle = new Circle();
        circle.setId(1);
        shapeMap.put(circle.getId(),circle);

        Square square = new Square();
        square.setId(2);
        shapeMap.put(square.getId(),square);

        Rectangle rectangle = new Rectangle();
        rectangle.setId(3);
        shapeMap.put(rectangle.getId(),rectangle);
    }

}

